package com.ztesoft.web.datarecovery.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ztesoft.core.cache.EhCacheService;
import com.ztesoft.core.common.Page;
import com.ztesoft.core.convert.IArgConversionService;
import com.ztesoft.core.db.ds.DynamicDataSourceManager;
import com.ztesoft.core.idproduce.ISequenceGenerator;
import com.ztesoft.core.threadpool.GeneralThreadPool;
import com.ztesoft.core.threadpool.ThreadPoolFactory;
import com.ztesoft.framework.exception.BaseAppException;
import com.ztesoft.framework.log.ZTEsoftLogManager;
import com.ztesoft.framework.util.Utils;
import com.ztesoft.web.baseconfig.db.dao.DmDataStateDao;
import com.ztesoft.web.baseconfig.db.dao.DmPlanDao;
import com.ztesoft.web.baseconfig.db.dao.DmSrcTableDao;
import com.ztesoft.web.baseconfig.db.dao.DmStrategyDao;
import com.ztesoft.web.baseconfig.db.dao.DmStrategyDataobjRelDao;
import com.ztesoft.web.baseconfig.db.dao.DmTableRelDao;
import com.ztesoft.web.baseconfig.db.dao.DmTargetTableDao;
import com.ztesoft.web.baseconfig.db.dao.SubTableDefineDao;
import com.ztesoft.web.baseconfig.db.dao.TargetColMapDao;
import com.ztesoft.web.baseconfig.db.po.DmDataStatePO;
import com.ztesoft.web.baseconfig.db.po.DmStrategyDataobjRelPO;
import com.ztesoft.web.baseconfig.db.po.DmTableRelPO;
import com.ztesoft.web.baseconfig.db.po.DmTargetTablePO;
import com.ztesoft.web.baseconfig.db.po.SubTableDefinePO;
import com.ztesoft.web.baseconfig.service.IDmPlanRelationService;
import com.ztesoft.web.baseconfig.service.IDmSrcTableService;
import com.ztesoft.web.common.SubTableDefine;
import com.ztesoft.web.common.db.dao.DmDao;
import com.ztesoft.web.datarecovery.DataRecoveryThread;
import com.ztesoft.web.datarecovery.service.IDmDataRecoveryService;
import com.ztesoft.web.syncbaseinfo.service.BaseInfoService;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskDao;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskStageDao;
import com.ztesoft.web.taskgenerator.db.po.DmTaskPO;

/**
 * <Description> <br>
 * 
 * @author linjie<br>
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2016年4月20日 <br>
 * @since V1.0<br>
 * @see com.ztesoft.web.datarecovery.service.impl <br>
 */

@Service("dmDataRecoveryService")
public class DmDataRecoveryServiceImpl implements IDmDataRecoveryService {

	private static final ZTEsoftLogManager logger = ZTEsoftLogManager.getLogger(DmDataRecoveryServiceImpl.class);

	@Autowired
	private DmTaskDao dmTaskDao;

	@Autowired
	private DmPlanDao dmPlanDao;

	@Autowired
	private DmTaskStageDao dmTaskStageDao;

	@Autowired
	private IDmPlanRelationService dDmPlanRelationService;

	@Autowired
	private IDmSrcTableService iDmSrcTableService;

	@Autowired
	private SubTableDefine subTableDefine;

	@Autowired
	private DmDataStateDao dmDataStateDao;

	@Autowired
	private DmDao dmDao;

	@Autowired
	private DmTableRelDao dmTableRelDao;

	@Autowired
	private TargetColMapDao targetColMapDao;

	@Autowired
	private DmStrategyDataobjRelDao dmStrategyDataobjRelDao;

	@Autowired
	private DmSrcTableDao dmSrcTableDao;

	@Autowired
	private SubTableDefineDao subTableDefineDao;

	@Autowired
	private DmTargetTableDao dmTargetTableDao;

	@Autowired
	private DmStrategyDao dmStrategyDao;

	@Autowired
	private BaseInfoService baseInfoService;
	@Autowired
	private DynamicDataSourceManager dynamicDataSourceManager;// 数据库 连接

	// 缓存内存
	@Resource(name = "frameworkEhCacheService")
	private EhCacheService dmsCacheService;

	/**
	 * 查询条件转换成Arg类的服务接口
	 */
	@Resource(name = "defaultArgConversionService")
	private IArgConversionService argConversionService;

	/**
	 * 主键生成器
	 */
	@Resource(name = "sequenceProcGenerator")
	private ISequenceGenerator sequenceGenerator;

	/**
	 * 数据恢复界面
	 */
	@Override
	public Page<DmTaskPO> queryRecordByPageForDataRecovery(DmTaskPO record, Page<DmTaskPO> resultPage)
			throws BaseAppException {
		if ("".equals(record.getStartTimeStr())) {
			record.setStartTimeStr(null);
		}
		if ("".equals(record.getEndTimeStr())) {
			record.setEndTimeStr(null);
		}
		resultPage = dmTaskDao.queryRecordByPageForDataRecovery(record, resultPage);
		return resultPage;
	}

	/**
	 * 数据恢复
	 */
	@Override
	public Map<String, Integer> dataRecovery(String dmTaskIds) {
		Map<String, Integer> result = new HashMap<String, Integer>();
		result.put("success", 1);
		int subTable_TaskId = 0;
		String[] dmTaskIdss = dmTaskIds.split(",");
		boolean subFlag = false;
		for (int i = 0; i < dmTaskIdss.length; i++) {
			// 判断是否存在分表或者从表
			// 查找任务对应的源数据ID
			List<DmStrategyDataobjRelPO> dsdrPOList = dmStrategyDataobjRelDao.selectByDmTaskId(Integer
					.parseInt(dmTaskIdss[i]));
			for (DmStrategyDataobjRelPO dsdrPO : dsdrPOList) {
				// 判断该源数据是否有分表
				SubTableDefinePO stdPO = new SubTableDefinePO();
				stdPO.setSourceDataId(dsdrPO.getSourceDataId());
				List<SubTableDefinePO> stdPOList = subTableDefineDao.selectBySourceDataId(stdPO);
				if (stdPOList.size() > 1) {// 有分表
					subTable_TaskId = Integer.parseInt(dmTaskIdss[i]);
					subFlag = true;
					break;
				}
				// 判断该源数据是否有从表
				List<DmTableRelPO> dtrList = dmTableRelDao.selectByRelDataId(dsdrPO.getSourceDataId());
				if (dtrList.size() != 0) {// 有从表
					subTable_TaskId = Integer.parseInt(dmTaskIdss[i]);
					subFlag = true;
					break;
				}
			}
			// 判断是否有未完成的子任务
			if (hasSubTaskRun(Integer.parseInt(dmTaskIdss[i]))) {
				result.put("subTask", Integer.parseInt(dmTaskIdss[i]));
				return result;
			}
			// 判断是否是派生的任务，且其他任务有正在数据恢复的（不同对同一个表操作，表会锁死）
			// 先获取这一堆的任务（父任务和所有子任务，如果有子任务的话）
//			List<DmTaskPO> dtPOList = getFatherAndAllChildrenTask(Integer.parseInt(dmTaskIdss[i]));
//			for (DmTaskPO dtPO : dtPOList) {
//				if ("0DS".equals(dtPO.getState())) {
//					result.put("subTaskIsRun", dtPO.getDmTaskId());
//					return result;
//				}
//			}
			// 判断目标表的can_data_recovery字段是否是1
			List<DmTargetTablePO> dttPOList = dmTargetTableDao.getTargetTableInfo(Integer.parseInt(dmTaskIdss[i]));
			if (dttPOList.size() != 0) {
				for (DmTargetTablePO dttPO : dttPOList) {
					if (dttPO.getCanDataRecovery() == 0) {
						result.put("noRecoveryTask", Integer.parseInt(dmTaskIdss[i]));
						return result;
					}
				}
			}
		}
		if (subFlag) {
			result.put("subTable", subTable_TaskId);
			return result;
		}
		int queueSize = dmTaskIdss.length;
		List<Future<String>> futureList = new ArrayList<Future<String>>(dmTaskIdss.length);
		GeneralThreadPool pool = null;
		try {
			// 创建线程池，大小为任务个数
			pool = ThreadPoolFactory.createGeneralBoundedThreadPool("数据恢复开始：任务数：" + queueSize, queueSize, queueSize);
		} catch (Exception e) {
			logger.error("数据恢复异常：创建线程池异常，任务数：" + queueSize, e);
			result.put("success", 0);
			return result;
		}
		for (int i = 0; i < queueSize; i++) {
			DataRecoveryThread thread = new DataRecoveryThread(Integer.parseInt(dmTaskIdss[i]));
			Future<String> future = pool.submit(thread);
			futureList.add(future);
		}
		pool.shutDown();
		return result;
	}
	
	private List<DmTaskPO> getFatherAndAllChildrenTask(Integer dmTaskId) {
		List<DmTaskPO> result = new ArrayList<DmTaskPO>();
		DmTaskPO dtPO = dmTaskDao.selectByPrimaryKey(dmTaskId);
		if (Utils.notEmpty(dtPO)) {
			if (Utils.notEmpty(dtPO.getParentTaskId())) {// 有父节点，说明自己是子任务
				result = dmTaskDao.selectByParentTaskId(dtPO.getParentTaskId());
				result.add(dmTaskDao.selectByPrimaryKey(dtPO.getParentTaskId()));
			} else {// 没有父节点，说明自己有可能是父任务
				result = dmTaskDao.selectByParentTaskId(dmTaskId);
				result.add(dtPO);
			}
		}
		return result;
	}

	/**
	 * 判断任务下是否有正在运行的子任务
	 * 
	 * @param taskId
	 * @return
	 */
	private boolean hasSubTaskRun(Integer taskId) {
		boolean subTaskFlag = false;
		List<DmTaskPO> dtPOList = dmTaskDao.selectByParentTaskId(taskId);
		for (DmTaskPO po : dtPOList) {
			if (!(po.getState().equals("00A") || po.getState().equals("00C"))) {
				return true;
			}
			subTaskFlag = hasSubTaskRun(po.getDmTaskId());
			if (subTaskFlag) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 数据恢复完成
	 */
	@Override
	public int dataRecoveryOK(String dmTaskIds) {
		String[] dmTaskIdss = dmTaskIds.split(",");
		DmDataStatePO ddsPO = new DmDataStatePO();
		ddsPO.setState(3);
		ddsPO.setStateDate(new Date());
		for (int i = 0; i < dmTaskIdss.length; i++) {
			DmTaskPO dtPO = new DmTaskPO();
			// 更新任务表，状态为-0SS
			dtPO.setDmTaskId(Integer.parseInt(dmTaskIdss[i]));
			dtPO.setState("0SS");
			dtPO.setStateDate(new Date());
			dmTaskDao.updateByPrimaryKeySelective(dtPO);
			// 更新DM_DATA_STATE表数据，状态为 3—已恢复，计划可以继续进行数据归档
			ddsPO.setDmTaskId(Integer.parseInt(dmTaskIdss[i]));
			dmDataStateDao.updateByDmTaskIdSelective(ddsPO);
			// 更新静态内存中的数据，状态为 3—已恢复，计划可以继续进行数据归档
			// 先获取dmPlanId
			dtPO = dmTaskDao.selectByPrimaryKey(Integer.parseInt(dmTaskIdss[i]));
			dmsCacheService.put("dmsCache", "dataRecovery_" + dtPO.getDmPlanId(), 3);
		}
		return 1;
	}
}
